﻿Imports WiremetModel.Entities.SupplyOrders
Imports WiremetModel.Entities
Imports WiremetModel.Exceptions
Imports GMap.NET
Imports GMap.NET.WindowsForms
Imports CrystalDecisions.CrystalReports.Engine

Public Class MiscellaneousOrderView

    Private _unitOfWork As UnitOfWork
    Private _miscellaneousOrderDictionary As IDictionary(Of Integer, MiscellaneousOrder)
    Private _supplierLocationOverlay As GMapOverlay
    Private _detailsPanelWidth As Integer


    Private Structure Filter
        Public orderNumber As String
        Public supplierId As Integer
        Public submitDate As Date?
        Public productTypeId As Integer
        Public productId As Integer
    End Structure


    Public Sub New()
        InitializeComponent()
        _unitOfWork = New UnitOfWork()
        RefreshView()
    End Sub

    Private Sub MiscellaneousOrderView_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs) Handles Me.FormClosed
        _unitOfWork.Dispose()
    End Sub

    Private Sub RefreshView()
        RefreshViewData()
        RefreshMiscellaneousOrderTable(_miscellaneousOrderDictionary.Values)
    End Sub

    Private Sub RefreshViewData()

        Dim miscellaneousOrderRepository As New Repository(Of MiscellaneousOrder)(_unitOfWork)
        _miscellaneousOrderDictionary = miscellaneousOrderRepository.GetAll().ToDictionary(Function(x) x.Id, Function(x) x)
        RefreshFilterComboBoxData()

    End Sub

    Private Sub RefreshFilterComboBoxData()

        Dim productTypeRepository As New Repository(Of ProductType)(_unitOfWork)
        Dim productRepository As New Repository(Of Product)(_unitOfWork)
        Dim supplierRepository As New Repository(Of Supplier)(_unitOfWork)

        Dim productTypeList As IEnumerable(Of ProductType) = productTypeRepository.GetAll()
        Dim productList As IEnumerable(Of Product) = productRepository.GetAll()
        Dim supplierList As IEnumerable(Of Supplier) = supplierRepository.GetAll()

        InitializeFilterComboBox(cmb_Filter_ProductType, productTypeList)
        InitializeFilterComboBox(cmb_Filter_ProductName, productList)
        InitializeFilterComboBox(cmb_Filter_Supplier, supplierList)

    End Sub


    Private Sub InitializeFilterComboBox(ByRef inputComboBox As ComboBox, ByVal data As IEnumerable(Of Object))
        inputComboBox.DataSource = New BindingSource(data, Nothing)
        inputComboBox.AutoCompleteCustomSource.Clear()
        inputComboBox.AutoCompleteCustomSource.AddRange(data.Select(Function(x) x.ToString()).ToArray())
        inputComboBox.SelectedIndex = -1
    End Sub


    Private Sub RefreshMiscellaneousOrderTable(ByVal miscellaneousOrderList As IEnumerable(Of MiscellaneousOrder))

        dgv_MiscellaneousOrder.Rows.Clear()
        For Each miscellaneousOrder As MiscellaneousOrder In miscellaneousOrderList.OrderByDescending(Function(x) x.OrderNumber)
            dgv_MiscellaneousOrder.Rows.Add(
                miscellaneousOrder.Id,
                miscellaneousOrder.OrderNumber,
                miscellaneousOrder.Supplier.CompanyName,
                miscellaneousOrder.SubmitDate.ToShortDateString(),
                If(miscellaneousOrder.ExpectedDeliveryDate.HasValue, miscellaneousOrder.ExpectedDeliveryDate.Value.ToShortDateString(), String.Empty),
                miscellaneousOrder.OrderLines.Sum(Function(x) Math.Round(x.Quantity * x.UnitPrice, 2)).ToString() & " " & miscellaneousOrder.Currency.Nazwa
            )
        Next
    End Sub


    Private Function GetSelectedMiscellaneousOrder() As MiscellaneousOrder
        Return _miscellaneousOrderDictionary(CInt(dgv_MiscellaneousOrder.SelectedRows(0).Cells("MiscellaneousOrderId").Value))
    End Function

    Private Sub RefreshDetailsPanel()
        Dim miscellaneousOrder As MiscellaneousOrder = GetSelectedMiscellaneousOrder()

        tb_Employee.Text = miscellaneousOrder.Employee.ToString()
        tb_Note.Text = miscellaneousOrder.Note
        Dim supplierAddres As SupplierAddress = miscellaneousOrder.Supplier.SupplierAddresses.FirstOrDefault(Function(x) x.Address.Id = miscellaneousOrder.SubmitAddress.Id)
        tb_SubmitAddress.Text = If(IsNothing(supplierAddres), "Usunięty", supplierAddres.Description) & vbNewLine &
            miscellaneousOrder.SubmitAddress.ToString()

        tb_TelephoneNumber.Text = miscellaneousOrder.Supplier.TelephoneNumber
        tb_FaxNumber.Text = miscellaneousOrder.Supplier.FaxNumber
        tb_EmailAddress.Text = miscellaneousOrder.Supplier.EmailAddress

        dgv_MiscellaneousOrderLine.Rows.Clear()
        For Each miscellaneousOrderLine As MiscellaneousOrderLine In miscellaneousOrder.OrderLines

            dgv_MiscellaneousOrderLine.Rows.Add(
                miscellaneousOrderLine.Id,
                miscellaneousOrderLine.Product.ProductType.Name,
                miscellaneousOrderLine.Product.Name,
                miscellaneousOrderLine.Quantity,
                miscellaneousOrderLine.UnitPrice,
                Math.Round(miscellaneousOrderLine.UnitPrice * miscellaneousOrderLine.Quantity)
            )
        Next
    End Sub

    Private Sub dgv_MiscellaneousOrder_SelectionChanged(ByVal sender As Object, ByVal e As EventArgs) Handles dgv_MiscellaneousOrder.SelectionChanged
        If Not sc_OrderData.Panel2Collapsed AndAlso Not dgv_MiscellaneousOrder.SelectedRows.Count = 0 Then
            RefreshDetailsPanel()
        End If
    End Sub


#Region "Filter"

    Private Function CreateFilter() As Filter
        Return New Filter With
        {
            .orderNumber = tb_Filter_OrderNumber.Text.Trim(),
            .submitDate = If(dtp_Filter_SumbitDate.Checked, dtp_Filter_SumbitDate.Value, CType(Nothing, Date?)),
            .supplierId = If(IsNothing(cmb_Filter_Supplier.SelectedItem), 0, CType(cmb_Filter_Supplier.SelectedItem, Supplier).Id),
            .productTypeId = If(IsNothing(cmb_Filter_ProductType.SelectedItem), 0, CType(cmb_Filter_ProductType.SelectedItem, ProductType).Id),
            .productId = If(IsNothing(cmb_Filter_ProductName.SelectedItem), 0, CType(cmb_Filter_ProductName.SelectedItem, Product).Id)
        }
    End Function


    Private Function IsMiscellaneousOrderSatisfiedByFilter(ByVal miscellaneousOrder As MiscellaneousOrder, ByVal filter As Filter) As Boolean
        Return miscellaneousOrder.OrderNumber.StartsWith(filter.orderNumber, StringComparison.CurrentCultureIgnoreCase) AndAlso
            (filter.supplierId = 0 OrElse miscellaneousOrder.Supplier.Id = filter.supplierId) AndAlso
            (Not filter.submitDate.HasValue OrElse miscellaneousOrder.SubmitDate.ToShortDateString() = filter.submitDate.Value.ToShortDateString()) AndAlso
            (filter.productTypeId = 0 OrElse miscellaneousOrder.OrderLines.Any(Function(x) x.Product.ProductType.Id = filter.productTypeId)) AndAlso
            (filter.productId = 0 OrElse miscellaneousOrder.OrderLines.Any(Function(x) x.Product.Id = filter.productId))
    End Function


    Private Sub RunFilter(ByVal filter As Filter)
        Dim filteredMiscellaneousOrderList As New List(Of MiscellaneousOrder)

        For Each miscellaneousOrder As MiscellaneousOrder In _miscellaneousOrderDictionary.Values
            If IsMiscellaneousOrderSatisfiedByFilter(miscellaneousOrder, filter) Then
                filteredMiscellaneousOrderList.Add(miscellaneousOrder)
            End If
        Next

        RefreshMiscellaneousOrderTable(filteredMiscellaneousOrderList)
    End Sub


    Private Sub ClearFilter()
        tb_Filter_OrderNumber.Text = String.Empty
        dtp_Filter_SumbitDate.Value = Date.Now
        dtp_Filter_SumbitDate.Checked = False
        cmb_Filter_ProductName.ResetText()
        cmb_Filter_ProductName.SelectedIndex = -1
        cmb_Filter_ProductType.ResetText()
        cmb_Filter_ProductType.SelectedIndex = -1
    End Sub

    Private Sub btn_RunFilter_Click(sender As System.Object, e As System.EventArgs) Handles btn_RunFilter.Click
        RunFilter(CreateFilter())
    End Sub

    Private Sub btn_ClearFilter_Click(sender As System.Object, e As System.EventArgs) Handles btn_ClearFilter.Click
        ClearFilter()
        RefreshMiscellaneousOrderTable(_miscellaneousOrderDictionary.Values)
    End Sub

    Private Sub filterInput_KeyDown(sender As Object, e As KeyEventArgs) Handles tb_Filter_OrderNumber.KeyDown, cmb_Filter_ProductName.KeyDown, cmb_Filter_ProductType.KeyDown, cmb_Filter_Supplier.KeyDown, dtp_Filter_SumbitDate.KeyDown
        If e.KeyCode = Keys.Enter Then
            RunFilter(CreateFilter())
        End If
    End Sub
#End Region

    Private Sub EnsureMiscellaneousOrderIsSelected()
        If dgv_MiscellaneousOrder.SelectedRows.Count = 0 Then
            Throw New Exception("Proszę, wybierz zamówienie, aby kontynuować.")
        End If
    End Sub
    Private Sub PresentMiscellaneousOrderReport(ByVal miscellaneousOrder As MiscellaneousOrder)
        Dim miscellaneousOrderReport As ReportDocument = New MiscellaneousOrderReportService().GenerateReport(miscellaneousOrder)
        Dim reportPreviewForm As New frmPrintViewer(miscellaneousOrderReport, False)
        reportPreviewForm.WindowState = FormWindowState.Maximized
        reportPreviewForm.Show()
    End Sub

    Private Sub ts_btn_AddMiscellaneousOrder_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_AddMiscellaneousOrder.Click
        Try
            Dim miscellaneousOrderInputDialog As New MiscellaneousOrderInputDialog(_unitOfWork)
            If miscellaneousOrderInputDialog.ShowDialog = Windows.Forms.DialogResult.OK Then
                Cursor = Cursors.WaitCursor

                Dim miscellaneousOrder As MiscellaneousOrder = miscellaneousOrderInputDialog.MiscellaneousOrder
                Dim miscellaneousOrderRepository As New Repository(Of MiscellaneousOrder)(_unitOfWork)

                _unitOfWork.BeginTransaction()
                miscellaneousOrderRepository.Add(miscellaneousOrder)
                _unitOfWork.CommitTransaction()

                PresentMiscellaneousOrderReport(miscellaneousOrder)

                _miscellaneousOrderDictionary.Add(miscellaneousOrder.Id, miscellaneousOrder)
                RefreshMiscellaneousOrderTable(_miscellaneousOrderDictionary.Values)
                RefreshFilterComboBoxData()
                ClearFilter()
                RunFilter(CreateFilter())

            End If
        Catch ex As Exception
            If _unitOfWork.IsTransactionActive Then
                _unitOfWork.RollbackTransaction()
                _unitOfWork.DisposeTransaction()
            End If
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub ts_btn_EditMiscellaneousOrder_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_EditMiscellaneousOrder.Click
        Try
            EnsureMiscellaneousOrderIsSelected()
            Dim selectedMiscellaneousOrder As MiscellaneousOrder = GetSelectedMiscellaneousOrder()
            Dim miscellaneousOrderInputDialog As New MiscellaneousOrderInputDialog(selectedMiscellaneousOrder, _unitOfWork)

            If miscellaneousOrderInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Cursor = Cursors.WaitCursor

                Dim miscellaneousOrder As MiscellaneousOrder = miscellaneousOrderInputDialog.MiscellaneousOrder
                Dim miscellaneousOrderRepository As New Repository(Of MiscellaneousOrder)(_unitOfWork)

                _unitOfWork.BeginTransaction()
                miscellaneousOrderRepository.Update(miscellaneousOrder)
                _unitOfWork.CommitTransaction()

                PresentMiscellaneousOrderReport(miscellaneousOrder)

                _miscellaneousOrderDictionary(miscellaneousOrder.Id) = miscellaneousOrder
                RefreshMiscellaneousOrderTable(_miscellaneousOrderDictionary.Values)
                RefreshFilterComboBoxData()
                ClearFilter()
                RunFilter(CreateFilter())

            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub ts_btn_DeleteOrder_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_DeleteMiscellaneousOrder.Click
        Try
            EnsureMiscellaneousOrderIsSelected()
            Dim selectedMiscellaneousOrder As MiscellaneousOrder = GetSelectedMiscellaneousOrder()
            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewien?", "Uwaga", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)

            If confirmationDialogResult = DialogResult.Yes Then
                Cursor = Cursors.WaitCursor

                Dim miscellaneousOrderRepository As New Repository(Of MiscellaneousOrder)(_unitOfWork)

                _unitOfWork.BeginTransaction()
                miscellaneousOrderRepository.Delete(selectedMiscellaneousOrder)
                _unitOfWork.CommitTransaction()

                _miscellaneousOrderDictionary.Remove(selectedMiscellaneousOrder.Id)
                RefreshMiscellaneousOrderTable(_miscellaneousOrderDictionary.Values)

                MessageBox.Show("Zamówienie zostało usunięte.", "Potwierdzenie", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub ts_btn_RefreshView_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_RefreshView.Click
        Try
            Cursor = Cursors.WaitCursor
            _unitOfWork.Dispose()
            _unitOfWork = New UnitOfWork()
            RefreshViewData()
            ClearFilter()
            RunFilter(CreateFilter())

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub ts_btn_CopyOrder_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_CopyOrder.Click
        Try
            EnsureMiscellaneousOrderIsSelected()
            Dim selectedMiscellaneousOrder As MiscellaneousOrder = GetSelectedMiscellaneousOrder()
            Dim copiedOrder As New MiscellaneousOrder With {
                .Currency = selectedMiscellaneousOrder.Currency,
                .Employee = selectedMiscellaneousOrder.Employee,
                .Note = selectedMiscellaneousOrder.Note,
                .OrderLines = selectedMiscellaneousOrder.OrderLines.Select(Function(x) New MiscellaneousOrderLine With {
                                                                               .MeasureUnit = x.MeasureUnit,
                                                                               .Product = x.Product,
                                                                               .Quantity = x.Quantity,
                                                                               .UnitPrice = x.UnitPrice
                                                                           }).ToList(),
                .SubmitAddress = selectedMiscellaneousOrder.SubmitAddress,
                .SubmitDate = Date.Now.Date,
                .Supplier = selectedMiscellaneousOrder.Supplier
            }
            '.ExpectedDeliveryDate = selectedMiscellaneousOrder.ExpectedDeliveryDate,
            For Each orderLine As MiscellaneousOrderLine In copiedOrder.OrderLines
                orderLine.MiscellaneousOrder = copiedOrder
            Next

            Dim miscellaneousOrderInputDialog As New MiscellaneousOrderInputDialog(copiedOrder, _unitOfWork)
            If miscellaneousOrderInputDialog.ShowDialog = Windows.Forms.DialogResult.OK Then
                Cursor = Cursors.WaitCursor

                Dim miscellaneousOrder As MiscellaneousOrder = miscellaneousOrderInputDialog.MiscellaneousOrder
                Dim miscellaneousOrderRepository As New Repository(Of MiscellaneousOrder)(_unitOfWork)

                _unitOfWork.BeginTransaction()
                miscellaneousOrderRepository.Add(miscellaneousOrder)
                _unitOfWork.CommitTransaction()

                PresentMiscellaneousOrderReport(miscellaneousOrder)

                _miscellaneousOrderDictionary.Add(miscellaneousOrder.Id, miscellaneousOrder)
                RefreshMiscellaneousOrderTable(_miscellaneousOrderDictionary.Values)
                RefreshFilterComboBoxData()
                ClearFilter()
                RunFilter(CreateFilter())

            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub ts_btn_PrintMiscellaneousOrder_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_PrintMiscellaneousOrder.Click
        Try
            EnsureMiscellaneousOrderIsSelected()
            Cursor = Cursors.WaitCursor
            Dim selectedMiscellaneousOrder As MiscellaneousOrder = GetSelectedMiscellaneousOrder()
            PresentMiscellaneousOrderReport(selectedMiscellaneousOrder)
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub ChangeDetailsPanelVisibility()
        If sc_OrderData.Panel2Collapsed Then
            sc_OrderData.Panel2Collapsed = False
            Me.Width += _detailsPanelWidth + sc_OrderData.SplitterWidth
        Else
            _detailsPanelWidth = sc_OrderData.Panel2.Width
            Me.Width -= _detailsPanelWidth + sc_OrderData.SplitterWidth
            sc_OrderData.Panel2Collapsed = True
        End If
        Refresh()
    End Sub

    Private Sub ts_btn_Details_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_Details.Click
        ChangeDetailsPanelVisibility()
        RefreshDetailsPanel()
    End Sub

    
End Class